home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 25 / AMIGAplus Sonderheft 25 (2000)(Falke)(DE)(Track 1 of 4)[!].iso / PublicDomain / Anwendungen / DetotterButton / DetotterMouseButton.mod < prev    next >
Text File  |  2000-03-23  |  14KB  |  363 lines

  1. |##########|
  2. |#MAGIC   #|GNOLIEBE
  3. |#PROJECT #|"DetotterMouseButton"
  4. |#PATHS   #|"StdProject"
  5. |#LINK    #|"c:"
  6. |#GUIDE   #|""
  7. |#STACK   #|"4096"
  8. |#FLAGS   #|xx-x-x--xxx-xxx-x---------------
  9. |#USERSW  #|-x------------------------------
  10. |#USERMASK#|-x------------------------------
  11. |#SWITCHES#|xx---xxxxx-xx---
  12. |##########|
  13.  
  14. MODULE DetotterMouseButton;
  15.  
  16. (**************************************************************************
  17.  *
  18.  * DetotterMouseButton.mod
  19.  *   based on Swap_Buttons.c from the Amiga developer CD V1.1
  20.  *
  21.  * This detotters a button of an old mouse.
  22.  * The Cluster code installs and removes the input.device handler and
  23.  * manages the timer messages.
  24.  *
  25.  * The handler is written in assembly code since it is important that
  26.  * handlers be as fast as possible while processing the input events.
  27.  *
  28.  *)
  29.  
  30. $$IF Final THEN
  31.   $$RangeChk    := FALSE
  32.   $$OverflowChk := FALSE
  33.   $$ReturnChk   := FALSE
  34.   $$StrZeroChk  := FALSE
  35.   $$StackChk    := FALSE
  36.   $$NilChk      := FALSE
  37.   $$Debug       := FALSE
  38.   $$EntryCode   := FALSE
  39. $$END
  40.  
  41. FROM Input      IMPORT All;
  42. FROM System     IMPORT Regs;
  43. FROM Exec       IMPORT MsgGrp, InterruptPtr, SignalGrp, LibraryPtr;
  44.  
  45. TYPE
  46.   DetotterDataPtr = POINTER TO DetotterData;
  47.   DetotterData    =
  48.     RECORD
  49.       execBase       : LibraryPtr;    | Fast access to the ExecBase
  50.       delayedEvent   : InputEvent;    | Storage for the delayed release event
  51.       delayed        : BOOLEAN;       | Is delayedEvent valid?
  52.       qualifier      : Qualifiers;    | Qualifier bit for the processed mouse button
  53.       pressed        : QualifierSet;  | The qualifier bit is set if the virtual button is pressed
  54.       rawCode        : CARDINAL;      | Raw key code for the processed button
  55.       task           : TaskPtr;       | Main task
  56.       abortDelaySigSet,
  57.       delaySigSet    : TaskSigSet;    | Signals the main task listens to
  58.     END;
  59.  
  60. $$RangeChk    := FALSE
  61. $$OverflowChk := FALSE
  62. $$ReturnChk   := FALSE
  63. $$StrZeroChk  := FALSE
  64. $$StackChk    := FALSE
  65. $$NilChk      := FALSE
  66. $$Debug       := FALSE
  67. $$EntryCode   := FALSE
  68.  
  69. PROCEDURE Detotter (event IN A0 : InputEventPtr;
  70.                     data  IN A1 : DetotterDataPtr) : InputEventPtr;
  71. VAR
  72.   code      IN D2 : CARDINAL;
  73.   qualifier IN D3 : QualifierSet;
  74. |
  75. | The event list gets passed to you in a0.
  76. | The InputHandler.data field is passed to you in a1.
  77. |
  78. | On exit you must return the event list in d0.  In this way
  79. | you could add or remove items from the event list.
  80. |
  81. CONST
  82.   Signal  = -324;
  83.  
  84.   buttonMask      = CAST(QualifierSet,INTEGER(-1)) - QualifierSet:{leftButton, midButton, rightButton};
  85.  
  86.   | Compiler doesn't like this
  87.   |detotterDataPtr    = DetotterDataPtr(NIL);
  88.   |delayedEventOffset = detotterDataPtr.delayedEvent'PTR;
  89.   |delayedEventOffset = DetotterDataPtr(NIL).delayedEvent'ADR;
  90.  
  91. BEGIN
  92.   ASSEMBLE (
  93.     _Detotter:
  94.       move    event,-(a7)                     | Save the event list
  95.       move.l  d2-d3/a2,-(a7)                  | Save other registers
  96.  
  97. |
  98. | Since the event list could be a linked list, we start a loop
  99. | here to handle all of the events passed to us.
  100. |
  101.     CheckLoop:
  102. |
  103. | The actual button up/down events are transmitted as the
  104. | code field in RAWMOUSE events.  The code field must the be
  105. | checked and modified when needed on RAWMOUSE events.  If the
  106. | event is not a RAWMOUSE, we are done with it.
  107. |
  108.       move    event.qualifier,qualifier       | Get qualifier set ...
  109.       move    event.code,code                 | Get code ...
  110.       cmp     #Class.rawmouse,event.class     | Check for mouse
  111.       bne     FixQualifiers                   | If not, next...
  112.  
  113.       move    code,d0                         | Duplicate ...
  114.       bclr    #7,d0                           | Mask UP_PREFIX
  115.       cmp     data.rawCode,d0                 | Check for button
  116.       bne     FixQualifiers                   | No button to care about
  117.  
  118. |(* begin of debug block, if block is commented out, the thing should not crash
  119.  
  120.       | The button to detotter has changed
  121.       btst    #7,code                         | Is it pressed ?
  122.       beq     ButtonPressed
  123.  
  124.     ButtonReleased:                           | Button is physically released
  125.       lea     data.delayedEvent,a2
  126.       cmp     a2,event                        | Is this the message we delayed?
  127.       beq     PassDeferedRelease              | If yes, pass it without delaying again
  128.       tst     data.delayed                    | Is there a event delayed, already?
  129.       bne     RedeferRelease                  | Yes seems so
  130.  
  131.     DeferRelease:                             | A new release event occured
  132.       | InputEvent'SIZE = 22
  133.       move    event,-(a7)
  134.       |lea     data.delayedEvent,a2           | We have done this some lines before already
  135.       move.l  (event)+,(a2)+                  | Store this event
  136.       move.l  (event)+,(a2)+
  137.       move.l  (event)+,(a2)+
  138.       move.l  (event)+,(a2)+
  139.       move.l  (event)+,(a2)+
  140.       move.w  (event)+,(a2)+
  141.       move    (a7)+,event
  142.       move    #-1,data.delayed                | Mark this copy as valid
  143.  
  144.     RedeferRelease:
  145.       | There is already a deferred release event, flush the current only
  146.     SignalMainTask:                           | Tell the main task, that it has to start a timer
  147.       move.l  a0/a1/a6,-(a7)
  148.       move.l  data.execBase,a6
  149.       move.l  data.delaySigSet,d0
  150.       move.l  data.task,a1                    | Since data = a1 we have to write this last
  151.       jsr     Signal(a6)                      | Signal (main task, delay signal);
  152.       move.l  (a7)+,a0/a1/a6
  153.       bra     FlushMessage                    | Trash this message, since it is either stored or double
  154.  
  155.     PassDeferedRelease:                       | We shall pass this message without parsing
  156.       clr     data.delayed                    | This stops the delay state
  157.       clr     data.pressed                    | Let's clear the corresponding qualifier bit in our internal qualifier set
  158.       bra     NextEvent                       | This hasn't to be processed anymore, qualifiers are already correct
  159.  
  160.     ButtonPressed:
  161.       tst     data.delayed                    | Do we hold a delayed release event?
  162.       bne     AbortDelay                      | Yes, so we will flush this and the delayed event
  163.       move    data.qualifier,d0               | No, so we pass the button press event
  164.       clr.w   d1                              |   and refresh the internal qualifier set
  165.       bset    d0,d1                           |   according to this change
  166.       move    d1,data.pressed
  167.       bra     FixQualifiers
  168.  
  169.     AbortDelay:
  170.       clr     data.delayed                    | This stops the delay state, too
  171.       move.l  a0/a1/a6,-(a7)
  172.       move.l  data.execBase,a6
  173.       move.l  data.abortDelaySigSet,d0
  174.       move.l  data.task,a1                    | Since data = a1 we have to write this last
  175.       jsr     Signal(a6)                      | Signal (main task, delay abort signal);
  176.       move.l  (a7)+,a0/a1/a6
  177.  
  178.     FlushMessage:
  179.       move    #Input.noButton,code            | Setting code to noButton turns this message into a dummy event
  180.       bra     StoreEvent                      | This hasn't to be processed anymore, qualifiers are already correct
  181. | end of block *)
  182. |
  183. | Since we are changing mouse button events, we need to make
  184. | sure that we change the qualifiers on all of the messages.  The
  185. | mouse buttons are tracked in the message qualifiers
  186. | for use in such things as dragging.  To make sure that we continue
  187. | to drag correctly, we change the qualifiers.
  188. |
  189.     FixQualifiers:
  190.       move    data.qualifier,d0
  191.       bclr    d0,qualifier
  192.       or      data.pressed,qualifier          | Set the processed qualifier to the emulated state
  193.  
  194.     StoreEvent:
  195.       move    code,event.code                 | Save back...
  196.       move    qualifier,event.qualifier
  197.       |move.l #$123134,0  | provoke Enforcer
  198. |
  199. | The event list is linked via a pointer to the next event
  200. | in the first element of the structure.  That is why it is not
  201. | nessesary to use:  move.l ie_NextEvent(a0),d0
  202. |
  203. | The reason I move to d0 first is that this also checks for zero.
  204. | The last event in the list will have a NULL ie_NextEvent field.
  205. | This is NOT as standard EXEC list where the